//
//  SafeDecode.swift
//  
//
//  Created by bo wang on 2018/4/29.
//  Copyright © 2018年 tiny. All rights reserved.
//

import Foundation
import CoreGraphics

/// 将任意值安全的转换为Int，不能正常转换时返回默认值
/// - Parameters:
///   - any: 任意内容
///   - default: 不能转换时返回的默认值，默认为0
/// - Returns: 转换后的Int值
func safe_int(_ any: Any?, default: Int = 0) -> Int {
    return safe_int_or_nil(any, default: `default`)!
}

/// 将任意值安全的转换为Int，不能正常转换时返回默认值或者nil
/// - Parameters:
///   - any: 任意内容
///   - default: 不能转换时返回的默认值，默认为nil
/// - Returns: 转换后的Int值或nil
func safe_int_or_nil(_ any: Any?, default: Int? = nil) -> Int? {
    guard let obj = any else { return `default` }
    switch obj {
    case let v as Int:      return v
    case let v as String:   return Int(v) ?? `default`
    case let v as Float:    return Int(v)
    case let v as Double:   return Int(v)
    case let v as CGFloat:  return Int(v)
    case let v as Bool:     return v ? 1 : 0
    case let v as NSNumber: return v.intValue
    case let v as NSString: return v.integerValue
    case let v as CustomStringConvertible: return Int(String(describing: v)) ?? `default`
    default:                return `default`
    }
}

func safe_float(_ any: Any?, default: Float = 0) -> Float {
    return safe_float_or_nil(any, default: `default`)!
}

func safe_float_or_nil(_ any: Any?, default: Float? = nil) -> Float? {
    if let v = safe_double_or_nil(any) {
        return Float(v)
    }
    return `default`
}

func safe_double(_ any: Any?, default: Double = 0) -> Double {
    return safe_double_or_nil(any, default: `default`)!
}

func safe_double_or_nil(_ any: Any?, default: Double? = nil) -> Double? {
    guard let obj = any else { return `default` }
    switch obj {
    case let v as Int:      return Double(v)
    case let v as String:   return Double(v) ?? `default`
    case let v as Float:    return Double(v)
    case let v as Double:   return v
    case let v as CGFloat:  return Double(v)
    case let v as Bool:     return v ? 1.0 : 0.0
    case let v as NSNumber: return v.doubleValue
    case let v as NSString: return v.doubleValue
    case let v as CustomStringConvertible: return Double(String(describing: v)) ?? `default`
    default:                return `default`
    }
}

func safe_string(_ any: Any?, default: String = "") -> String {
    return safe_string_or_nil(any, default: `default`)!
}

func safe_string_or_nil(_ any: Any?, default: String? = nil) -> String? {
    guard let obj = any else { return `default` }
    switch obj {
    case let v as Int:      return String(v)
    case let v as String:   return v
    case let v as Character: return String(v)
    case let v as Float:    return String(v)
    case let v as Double:   return String(v)
    case let v as CGFloat:  return String(Float(v))
    case let v as Bool:     return "\(v)"
    case let v as NSNumber: return v.stringValue
    case let v as NSString: return v as String
    case let v as CustomStringConvertible: return String(describing: v)
    case _ as NSNull:       return "null"
    default:                return `default`
    }
}

func safe_bool(_ any: Any?, default: Bool = false) -> Bool {
    return safe_bool_or_nil(any, default: `default`)!
}

func safe_bool_or_nil(_ any: Any?, default: Bool? = nil) -> Bool? {
    guard let obj = any else { return `default` }

    if let v = obj as? Bool {
        return v
    }
    
    if let v = safe_int_or_nil(any, default: nil) {
        return v != 0
    }
    return `default`
}
